<!DOCTYPE html><html><head><meta charset="utf-8"><style>body {
  width: 45em;
  border: 1px solid #ddd;
  outline: 1300px solid #fff;
  margin: 16px auto;
}

body .markdown-body
{
  padding: 30px;
}

@font-face {
  font-family: fontawesome-mini;
  src: url(data:font/woff;charset=utf-8;base64,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) format('woff');
}

@font-face {
  font-family: octicons-anchor;
  src: url(data:font/woff;charset=utf-8;base64,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) format('woff');
}

.markdown-body {
  font-family: sans-serif;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  color: #333333;
  overflow: hidden;
  font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  word-wrap: break-word;
}

.markdown-body a {
  background: transparent;
}

.markdown-body a:active,
.markdown-body a:hover {
  outline: 0;
}

.markdown-body b,
.markdown-body strong {
  font-weight: bold;
}

.markdown-body mark {
  background: #ff0;
  color: #000;
  font-style: italic;
  font-weight: bold;
}

.markdown-body sub,
.markdown-body sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}
.markdown-body sup {
  top: -0.5em;
}
.markdown-body sub {
  bottom: -0.25em;
}

.markdown-body h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

.markdown-body img {
  border: 0;
}

.markdown-body hr {
  -moz-box-sizing: content-box;
  box-sizing: content-box;
  height: 0;
}

.markdown-body pre {
  overflow: auto;
}

.markdown-body code,
.markdown-body kbd,
.markdown-body pre,
.markdown-body samp {
  font-family: monospace, monospace;
  font-size: 1em;
}

.markdown-body input {
  color: inherit;
  font: inherit;
  margin: 0;
}

.markdown-body html input[disabled] {
  cursor: default;
}

.markdown-body input {
  line-height: normal;
}

.markdown-body input[type="checkbox"] {
  box-sizing: border-box;
  padding: 0;
}

.markdown-body table {
  border-collapse: collapse;
  border-spacing: 0;
}

.markdown-body td,
.markdown-body th {
  padding: 0;
}

.markdown-body .codehilitetable {
  border: 0;
  border-spacing: 0;
}

.markdown-body .codehilitetable tr {
  border: 0;
}

.markdown-body .codehilitetable pre,
.markdown-body .codehilitetable div.codehilite {
  margin: 0;
}

.markdown-body .linenos,
.markdown-body .code,
.markdown-body .codehilitetable td {
  border: 0;
  padding: 0;
}

.markdown-body td:not(.linenos) .linenodiv {
  padding: 0 !important;
}

.markdown-body .code {
  width: 100%;
}

.markdown-body .linenos div pre,
.markdown-body .linenodiv pre,
.markdown-body .linenodiv {
  border: 0;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
  -webkit-border-top-left-radius: 3px;
  -webkit-border-bottom-left-radius: 3px;
  -moz-border-radius-topleft: 3px;
  -moz-border-radius-bottomleft: 3px;
  border-top-left-radius: 3px;
  border-bottom-left-radius: 3px;
}

.markdown-body .code div pre,
.markdown-body .code div {
  border: 0;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
  -webkit-border-top-right-radius: 3px;
  -webkit-border-bottom-right-radius: 3px;
  -moz-border-radius-topright: 3px;
  -moz-border-radius-bottomright: 3px;
  border-top-right-radius: 3px;
  border-bottom-right-radius: 3px;
}

.markdown-body * {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.markdown-body input {
  font: 13px Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
  line-height: 1.4;
}

.markdown-body a {
  color: #4183c4;
  text-decoration: none;
}

.markdown-body a:hover,
.markdown-body a:focus,
.markdown-body a:active {
  text-decoration: underline;
}

.markdown-body hr {
  height: 0;
  margin: 15px 0;
  overflow: hidden;
  background: transparent;
  border: 0;
  border-bottom: 1px solid #ddd;
}

.markdown-body hr:before,
.markdown-body hr:after {
  display: table;
  content: " ";
}

.markdown-body hr:after {
  clear: both;
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
  margin-top: 15px;
  margin-bottom: 15px;
  line-height: 1.1;
}

.markdown-body h1 {
  font-size: 30px;
}

.markdown-body h2 {
  font-size: 21px;
}

.markdown-body h3 {
  font-size: 16px;
}

.markdown-body h4 {
  font-size: 14px;
}

.markdown-body h5 {
  font-size: 12px;
}

.markdown-body h6 {
  font-size: 11px;
}

.markdown-body blockquote {
  margin: 0;
}

.markdown-body ul,
.markdown-body ol {
  padding: 0;
  margin-top: 0;
  margin-bottom: 0;
}

.markdown-body ol ol,
.markdown-body ul ol {
  list-style-type: lower-roman;
}

.markdown-body ul ul ol,
.markdown-body ul ol ol,
.markdown-body ol ul ol,
.markdown-body ol ol ol {
  list-style-type: lower-alpha;
}

.markdown-body dd {
  margin-left: 0;
}

.markdown-body code,
.markdown-body pre,
.markdown-body samp {
  font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
  font-size: 12px;
}

.markdown-body pre {
  margin-top: 0;
  margin-bottom: 0;
}

.markdown-body kbd {
  background-color: #e7e7e7;
  background-image: -moz-linear-gradient(#fefefe, #e7e7e7);
  background-image: -webkit-linear-gradient(#fefefe, #e7e7e7);
  background-image: linear-gradient(#fefefe, #e7e7e7);
  background-repeat: repeat-x;
  border-radius: 2px;
  border: 1px solid #cfcfcf;
  color: #000;
  padding: 3px 5px;
  line-height: 10px;
  font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
  display: inline-block;
}

.markdown-body>*:first-child {
  margin-top: 0 !important;
}

.markdown-body>*:last-child {
  margin-bottom: 0 !important;
}

.markdown-body .headeranchor-link {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  display: block;
  padding-right: 6px;
  padding-left: 30px;
  margin-left: -30px;
}

.markdown-body .headeranchor-link:focus {
  outline: none;
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
  position: relative;
  margin-top: 1em;
  margin-bottom: 16px;
  font-weight: bold;
  line-height: 1.4;
}

.markdown-body h1 .headeranchor,
.markdown-body h2 .headeranchor,
.markdown-body h3 .headeranchor,
.markdown-body h4 .headeranchor,
.markdown-body h5 .headeranchor,
.markdown-body h6 .headeranchor {
  display: none;
  color: #000;
  vertical-align: middle;
}

.markdown-body h1:hover .headeranchor-link,
.markdown-body h2:hover .headeranchor-link,
.markdown-body h3:hover .headeranchor-link,
.markdown-body h4:hover .headeranchor-link,
.markdown-body h5:hover .headeranchor-link,
.markdown-body h6:hover .headeranchor-link {
  height: 1em;
  padding-left: 8px;
  margin-left: -30px;
  line-height: 1;
  text-decoration: none;
}

.markdown-body h1:hover .headeranchor-link .headeranchor,
.markdown-body h2:hover .headeranchor-link .headeranchor,
.markdown-body h3:hover .headeranchor-link .headeranchor,
.markdown-body h4:hover .headeranchor-link .headeranchor,
.markdown-body h5:hover .headeranchor-link .headeranchor,
.markdown-body h6:hover .headeranchor-link .headeranchor {
  display: inline-block;
}

.markdown-body h1 {
  padding-bottom: 0.3em;
  font-size: 2.25em;
  line-height: 1.2;
  border-bottom: 1px solid #eee;
}

.markdown-body h2 {
  padding-bottom: 0.3em;
  font-size: 1.75em;
  line-height: 1.225;
  border-bottom: 1px solid #eee;
}

.markdown-body h3 {
  font-size: 1.5em;
  line-height: 1.43;
}

.markdown-body h4 {
  font-size: 1.25em;
}

.markdown-body h5 {
  font-size: 1em;
}

.markdown-body h6 {
  font-size: 1em;
  color: #777;
}

.markdown-body p,
.markdown-body blockquote,
.markdown-body ul,
.markdown-body ol,
.markdown-body dl,
.markdown-body table,
.markdown-body pre,
.markdown-body .admonition {
  margin-top: 0;
  margin-bottom: 16px;
}

.markdown-body hr {
  height: 4px;
  padding: 0;
  margin: 16px 0;
  background-color: #e7e7e7;
  border: 0 none;
}

.markdown-body ul,
.markdown-body ol {
  padding-left: 2em;
}

.markdown-body ul ul,
.markdown-body ul ol,
.markdown-body ol ol,
.markdown-body ol ul {
  margin-top: 0;
  margin-bottom: 0;
}

.markdown-body li>p {
  margin-top: 16px;
}

.markdown-body dl {
  padding: 0;
}

.markdown-body dl dt {
  padding: 0;
  margin-top: 16px;
  font-size: 1em;
  font-style: italic;
  font-weight: bold;
}

.markdown-body dl dd {
  padding: 0 16px;
  margin-bottom: 16px;
}

.markdown-body blockquote {
  padding: 0 15px;
  color: #777;
  border-left: 4px solid #ddd;
}

.markdown-body blockquote>:first-child {
  margin-top: 0;
}

.markdown-body blockquote>:last-child {
  margin-bottom: 0;
}

.markdown-body table {
  display: block;
  width: 100%;
  overflow: auto;
  word-break: normal;
  word-break: keep-all;
}

.markdown-body table th {
  font-weight: bold;
}

.markdown-body table th,
.markdown-body table td {
  padding: 6px 13px;
  border: 1px solid #ddd;
}

.markdown-body table tr {
  background-color: #fff;
  border-top: 1px solid #ccc;
}

.markdown-body table tr:nth-child(2n) {
  background-color: #f8f8f8;
}

.markdown-body img {
  max-width: 100%;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.markdown-body code,
.markdown-body samp {
  padding: 0;
  padding-top: 0.2em;
  padding-bottom: 0.2em;
  margin: 0;
  font-size: 85%;
  background-color: rgba(0,0,0,0.04);
  border-radius: 3px;
}

.markdown-body code:before,
.markdown-body code:after {
  letter-spacing: -0.2em;
  content: "\00a0";
}

.markdown-body pre>code {
  padding: 0;
  margin: 0;
  font-size: 100%;
  word-break: normal;
  white-space: pre;
  background: transparent;
  border: 0;
}

.markdown-body .codehilite {
  margin-bottom: 16px;
}

.markdown-body .codehilite pre,
.markdown-body pre {
  padding: 16px;
  overflow: auto;
  font-size: 85%;
  line-height: 1.45;
  background-color: #f7f7f7;
  border-radius: 3px;
}

.markdown-body .codehilite pre {
  margin-bottom: 0;
  word-break: normal;
}

.markdown-body pre {
  word-wrap: normal;
}

.markdown-body pre code {
  display: inline;
  max-width: initial;
  padding: 0;
  margin: 0;
  overflow: initial;
  line-height: inherit;
  word-wrap: normal;
  background-color: transparent;
  border: 0;
}

.markdown-body pre code:before,
.markdown-body pre code:after {
  content: normal;
}

/* Admonition */
.markdown-body .admonition {
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  position: relative;
  border-radius: 3px;
  border: 1px solid #e0e0e0;
  border-left: 6px solid #333;
  padding: 10px 10px 10px 30px;
}

.markdown-body .admonition table {
  color: #333;
}

.markdown-body .admonition p {
  padding: 0;
}

.markdown-body .admonition-title {
  font-weight: bold;
  margin: 0;
}

.markdown-body .admonition>.admonition-title {
  color: #333;
}

.markdown-body .attention>.admonition-title {
  color: #a6d796;
}

.markdown-body .caution>.admonition-title {
  color: #d7a796;
}

.markdown-body .hint>.admonition-title {
  color: #96c6d7;
}

.markdown-body .danger>.admonition-title {
  color: #c25f77;
}

.markdown-body .question>.admonition-title {
  color: #96a6d7;
}

.markdown-body .note>.admonition-title {
  color: #d7c896;
}

.markdown-body .admonition:before,
.markdown-body .attention:before,
.markdown-body .caution:before,
.markdown-body .hint:before,
.markdown-body .danger:before,
.markdown-body .question:before,
.markdown-body .note:before {
  font: normal normal 16px fontawesome-mini;
  -moz-osx-font-smoothing: grayscale;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  line-height: 1.5;
  color: #333;
  position: absolute;
  left: 0;
  top: 0;
  padding-top: 10px;
  padding-left: 10px;
}

.markdown-body .admonition:before {
  content: "\f056\00a0";
  color: 333;
}

.markdown-body .attention:before {
  content: "\f058\00a0";
  color: #a6d796;
}

.markdown-body .caution:before {
  content: "\f06a\00a0";
  color: #d7a796;
}

.markdown-body .hint:before {
  content: "\f05a\00a0";
  color: #96c6d7;
}

.markdown-body .danger:before {
  content: "\f057\00a0";
  color: #c25f77;
}

.markdown-body .question:before {
  content: "\f059\00a0";
  color: #96a6d7;
}

.markdown-body .note:before {
  content: "\f040\00a0";
  color: #d7c896;
}

.markdown-body .admonition::after {
  content: normal;
}

.markdown-body .attention {
  border-left: 6px solid #a6d796;
}

.markdown-body .caution {
  border-left: 6px solid #d7a796;
}

.markdown-body .hint {
  border-left: 6px solid #96c6d7;
}

.markdown-body .danger {
  border-left: 6px solid #c25f77;
}

.markdown-body .question {
  border-left: 6px solid #96a6d7;
}

.markdown-body .note {
  border-left: 6px solid #d7c896;
}

.markdown-body .admonition>*:first-child {
  margin-top: 0 !important;
}

.markdown-body .admonition>*:last-child {
  margin-bottom: 0 !important;
}

/* progress bar*/
.markdown-body .progress {
  display: block;
  width: 300px;
  margin: 10px 0;
  height: 24px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  background-color: #ededed;
  position: relative;
  box-shadow: inset -1px 1px 3px rgba(0, 0, 0, .1);
}

.markdown-body .progress-label {
  position: absolute;
  text-align: center;
  font-weight: bold;
  width: 100%; margin: 0;
  line-height: 24px;
  color: #333;
  text-shadow: 1px 1px 0 #fefefe, -1px -1px 0 #fefefe, -1px 1px 0 #fefefe, 1px -1px 0 #fefefe, 0 1px 0 #fefefe, 0 -1px 0 #fefefe, 1px 0 0 #fefefe, -1px 0 0 #fefefe, 1px 1px 2px #000;
  -webkit-font-smoothing: antialiased !important;
  white-space: nowrap;
  overflow: hidden;
}

.markdown-body .progress-bar {
  height: 24px;
  float: left;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  background-color: #96c6d7;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(0, 0, 0, .1);
  background-size: 30px 30px;
  background-image: -webkit-linear-gradient(
    135deg, rgba(255, 255, 255, .4) 27%,
    transparent 27%,
    transparent 52%, rgba(255, 255, 255, .4) 52%,
    rgba(255, 255, 255, .4) 77%,
    transparent 77%, transparent
  );
  background-image: -moz-linear-gradient(
    135deg,
    rgba(255, 255, 255, .4) 27%, transparent 27%,
    transparent 52%, rgba(255, 255, 255, .4) 52%,
    rgba(255, 255, 255, .4) 77%, transparent 77%,
    transparent
  );
  background-image: -ms-linear-gradient(
    135deg,
    rgba(255, 255, 255, .4) 27%, transparent 27%,
    transparent 52%, rgba(255, 255, 255, .4) 52%,
    rgba(255, 255, 255, .4) 77%, transparent 77%,
    transparent
  );
  background-image: -o-linear-gradient(
    135deg,
    rgba(255, 255, 255, .4) 27%, transparent 27%,
    transparent 52%, rgba(255, 255, 255, .4) 52%,
    rgba(255, 255, 255, .4) 77%, transparent 77%,
    transparent
  );
  background-image: linear-gradient(
    135deg,
    rgba(255, 255, 255, .4) 27%, transparent 27%,
    transparent 52%, rgba(255, 255, 255, .4) 52%,
    rgba(255, 255, 255, .4) 77%, transparent 77%,
    transparent
  );
}

.markdown-body .progress-100plus .progress-bar {
  background-color: #a6d796;
}

.markdown-body .progress-80plus .progress-bar {
  background-color: #c6d796;
}

.markdown-body .progress-60plus .progress-bar {
  background-color: #d7c896;
}

.markdown-body .progress-40plus .progress-bar {
  background-color: #d7a796;
}

.markdown-body .progress-20plus .progress-bar {
  background-color: #d796a6;
}

.markdown-body .progress-0plus .progress-bar {
  background-color: #c25f77;
}

.markdown-body .candystripe-animate .progress-bar{
  -webkit-animation: animate-stripes 3s linear infinite;
  -moz-animation: animate-stripes 3s linear infinite;
  animation: animate-stripes 3s linear infinite;
}

@-webkit-keyframes animate-stripes {
  0% {
    background-position: 0 0;
  }

  100% {
    background-position: 60px 0;
  }
}

@-moz-keyframes animate-stripes {
  0% {
    background-position: 0 0;
  }

  100% {
    background-position: 60px 0;
  }
}

@keyframes animate-stripes {
  0% {
    background-position: 0 0;
  }

  100% {
    background-position: 60px 0;
  }
}

.markdown-body .gloss .progress-bar {
  box-shadow:
    inset 0 4px 12px rgba(255, 255, 255, .7),
    inset 0 -12px 0 rgba(0, 0, 0, .05);
}

/* Multimarkdown Critic Blocks */
.markdown-body .critic_mark {
  background: #ff0;
}

.markdown-body .critic_delete {
  color: #c82829;
  text-decoration: line-through;
}

.markdown-body .critic_insert {
  color: #718c00 ;
  text-decoration: underline;
}

.markdown-body .critic_comment {
  color: #8e908c;
  font-style: italic;
}

.markdown-body .headeranchor {
  font: normal normal 16px octicons-anchor;
  line-height: 1;
  display: inline-block;
  text-decoration: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.headeranchor:before {
  content: '\f05c';
}

.markdown-body .task-list-item {
  list-style-type: none;
}

.markdown-body .task-list-item+.task-list-item {
  margin-top: 3px;
}

.markdown-body .task-list-item input {
  margin: 0 4px 0.25em -20px;
  vertical-align: middle;
}

/* Media */
@media only screen and (min-width: 480px) {
  .markdown-body {
    font-size:14px;
  }
}

@media only screen and (min-width: 768px) {
  .markdown-body {
    font-size:16px;
  }
}

@media print {
  .markdown-body * {
    background: transparent !important;
    color: black !important;
    filter:none !important;
    -ms-filter: none !important;
  }

  .markdown-body {
    font-size:12pt;
    max-width:100%;
    outline:none;
    border: 0;
  }

  .markdown-body a,
  .markdown-body a:visited {
    text-decoration: underline;
  }

  .markdown-body .headeranchor-link {
    display: none;
  }

  .markdown-body a[href]:after {
    content: " (" attr(href) ")";
  }

  .markdown-body abbr[title]:after {
    content: " (" attr(title) ")";
  }

  .markdown-body .ir a:after,
  .markdown-body a[href^="javascript:"]:after,
  .markdown-body a[href^="#"]:after {
    content: "";
  }

  .markdown-body pre {
    white-space: pre;
    white-space: pre-wrap;
    word-wrap: break-word;
  }

  .markdown-body pre,
  .markdown-body blockquote {
    border: 1px solid #999;
    padding-right: 1em;
    page-break-inside: avoid;
  }

  .markdown-body .progress,
  .markdown-body .progress-bar {
    -moz-box-shadow: none;
    -webkit-box-shadow: none;
    box-shadow: none;
  }

  .markdown-body .progress {
    border: 1px solid #ddd;
  }

  .markdown-body .progress-bar {
    height: 22px;
    border-right: 1px solid #ddd;
  }

  .markdown-body tr,
  .markdown-body img {
    page-break-inside: avoid;
  }

  .markdown-body img {
    max-width: 100% !important;
  }

  .markdown-body p,
  .markdown-body h2,
  .markdown-body h3 {
    orphans: 3;
    widows: 3;
  }

  .markdown-body h2,
  .markdown-body h3 {
    page-break-after: avoid;
  }
}
</style><title>kernel2.1版本更新说明</title></head><body><article class="markdown-body"><h1 id="kernel21"><a name="user-content-kernel21" href="#kernel21" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>KERNEL2.1版本更新说明</h1>
<p><a href="https://developer.gnome.org/gtk3/stable/gtk-getting-started.html">https://developer.gnome.org/gtk3/stable/gtk-getting-started.html</a></p>
<ul>
<li>created by icesky @2016.12.06</li>
<li>文档版本 V1.0.0 (<em><a href="https://git.oschina.net/icesky1stm/XipKernel_Report/tree/master">点击此处获取最新版本</a></em> )</li>
</ul>
<div class="toc">
<ul>
<li><a href="#kernel21">KERNEL2.1版本更新说明</a><ul>
<li><a href="#1-kernel21">1. kernel2.1升级概述:</a><ul>
<li><a href="#11-zlog">1.1 升级日志库为使用修改版的zlog库</a></li>
<li><a href="#12">1.2 修改公共流水号获取方式为序列，适应集群部署要求</a></li>
<li><a href="#13-tfquartz">1.3 定时使用支持集群的tfquartz</a></li>
<li><a href="#14-kernel">1.4 制定了kernel的版本升级机制</a></li>
<li><a href="#15">1.5 其他调整</a></li>
</ul>
</li>
<li><a href="#2-kernel21kernelreadme210">2. kernel2.1修改详细描述(该部分取自于kernel/README中的2.1.0版本描述)</a><ul>
<li><a href="#21-kernel">2.1 增加kernel版本升级机制</a></li>
<li><a href="#22-kcfglib">2.2 修改了kcfglib</a></li>
<li><a href="#23-kloglib">2.3 修改了kloglib</a></li>
<li><a href="#24-kinitlib">2.4 修改了kinitlib</a></li>
<li><a href="#25-kdblib">2.5 修改了kdblib</a></li>
<li><a href="#26-kpublib">2.6 修改了kpublib</a></li>
<li><a href="#27-etcxipsyscfg">2.7 修改etc/XIPSYS.cfg</a></li>
<li><a href="#28-vdmpvdmp">2.8 (VDMP服务端)修改VDMP的服务端程序</a></li>
<li><a href="#29-inclkernel">2.9 修改/新增incl/kernel/的头文件：</a></li>
<li><a href="#210-tfquartzjar">2.10 新增了tfquartz的相关jar包,配置文件</a></li>
</ul>
</li>
<li><a href="#3">3. 开发环境升级步骤:</a><ul>
<li><a href="#31">3.1 更新配置文件:</a></li>
<li><a href="#32-binbinsh">3.2 更新可执行文件(bin和binsh)</a></li>
<li><a href="#33">3.3 数据库新建和初始化</a></li>
<li><a href="#33_1">3.3 头文件更新</a></li>
<li><a href="#34-kernel">3.4 kernel程序更新</a></li>
<li><a href="#35">3.5 启动服务</a></li>
<li><a href="#36-005b005c">3.6 补充更新（总线005B和005C的更新）</a></li>
</ul>
</li>
<li><a href="#4">4. 生产环境升级步骤:</a><ul>
<li><a href="#41">4.1 检查和调整(重要)</a></li>
<li><a href="#42">4.2 备份</a></li>
<li><a href="#43">4.3 更新时间选择</a></li>
<li><a href="#44">4.4 更新包更新</a></li>
<li><a href="#45">4.5 启动服务</a></li>
<li><a href="#46">4.6 业务验证</a></li>
</ul>
</li>
<li><a href="#5">5. 辅助检查和更新,以及特殊注意事项</a><ul>
<li><a href="#51-kernel">5.1 检查是否当地擅自修改了kernel</a></li>
<li><a href="#52-005b005c">5.2 总线更新005B和005C 补充更新</a></li>
<li><a href="#53">5.3 检查流水号重复区间非常非常重要</a></li>
<li><a href="#54-vdmp">5.4 VDMP的更新，除鞍山版本，其他地方都可以全量替换</a></li>
<li><a href="#55-xiplogid">5.5 xipLogId的使用长度调整，需要辅助调整其他更新</a></li>
<li><a href="#56-xiplogcreachanlogid">5.6 由于增加了XipLogCrea/Chan函数,增加logid关联，相关拆组包可以调整,以下为铁岭修改的业务程序</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<h2 id="1-kernel21"><a name="user-content-1-kernel21" href="#1-kernel21" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>1. kernel2.1升级概述:</h2>
<p>本次升级主要以渠道集群部署为目的升级,同时优化了部分kernel细节，同时规范化了kernel版本以及升级标准.</p>
<h3 id="11-zlog"><a name="user-content-11-zlog" href="#11-zlog" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>1.1 升级日志库为使用修改版的<a href="http://hardysimpson.github.io/zlog/UsersGuide-CN.html">zlog库</a></h3>
<ul>
<li>由于<em>zlog</em>内部使用线程和缓存，提高了日志输出效率。</li>
<li>日志格式实现可配置，有etc/xip_zlog.conf文件定义。</li>
<li>增加了渠道系统类似zjjk.sh的MONLOG的监控日志。</li>
<li>增加了渠道系统内部相互调用的XIPLOGID关联函数XipLogIdCrea和XipLogIdChan,在接收方日志中输出打印日志关联信息。</li>
<li>修改了XipLogId生成规则，参考UUID规则，具体为:<br />
   8位Time时间戳(HEX) + 3位Machine机器ID(XIPSYS.cfg配置) + 7位PID进程号(HEX) +2位INC自增计数器(staic 变量).</li>
</ul>
<h3 id="12"><a name="user-content-12" href="#12" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>1.2 修改公共流水号获取方式为序列，适应集群部署要求</h3>
<ul>
<li>kdblib增加了序列获取和序列创建的数据库操作函数，以供公共库和业务系统调用.</li>
<li>修改了kpublib下的get_tlsno系统公共流水号获取程序,关联上由此&rdquo;XipGetTraceno&rdquo;取流水号都将从序列中取得.</li>
<li>取得&rdquo;渠道-F&rdquo;配置信息中的SHMKEY作为序列名称，如原配置为A，则对应的序列为XIP_SEQUENCE_A，<br />
  如果序列不存在，会在第一次使用时按minseq和maxseq创建.(创建后再调整minseq和maxseq无效)<br />
<strong>需要核对，是否存在相同SHM_KEY，但是区间不同的，正常不应该出现.</strong></li>
</ul>
<h3 id="13-tfquartz"><a name="user-content-13-tfquartz" href="#13-tfquartz" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>1.3 定时使用支持集群的tfquartz</h3>
<ul>
<li>数据库新增tfquartz用户和权限, 需要有连接，写入，创建表权限,创建索引权限</li>
<li>依赖于JDK1.6及以上版本</li>
<li>由crontab的&rdquo;分 时 日 月 年&rdquo;5位，扩展为cron_config&rdquo;秒 分 时 日 月 周 年&rdquo;,其中&rdquo;周&rdquo;不需要配置为&rdquo;?&rdquo;<br />
<em>因此一般配置为 &ldquo;59 59 23 1 * ? *&ldquo;, 为每月一号的23点59分59秒执行.</em></li>
<li>详细的安装，配置，运维管理方法，见《tfquartz使用手册》</li>
<li>建立了用于记录定时的执行情况(执行时间，执行结果，执行的标准输出)的cron_log表.</li>
</ul>
<h3 id="14-kernel"><a name="user-content-14-kernel" href="#14-kernel" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>1.4 制定了kernel的版本升级机制</h3>
<ul>
<li>编写<a href="https://git.oschina.net/icesky1stm/XipKernel_Report/tree/master">《【规范】渠道kernel使用说明和升级规范V1.0.doc》</a></li>
<li>添加了makefie.version，提供&rdquo;XIP_KLIBS+版本号&rdquo;变量，供业务服务程序链接使用。</li>
<li>添加了src/incl/kernel/xipversion.h配合makefile.version使用。</li>
<li>统一版本，本次规定基础版本为2.0.0版本，为二代支付系统上线使用的kernel版本。</li>
</ul>
<h3 id="15"><a name="user-content-15" href="#15" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>1.5 其他调整</h3>
<ul>
<li>XIPSYS.cfg增加了XIPMACHID字段，用以区分不同集群中不同的渠道(不使用hostname)</li>
<li>XIPCHKIP.cfg默认配置信息调整，新建渠道默认为不控制，仅会警告.</li>
</ul>
<h2 id="2-kernel21kernelreadme210"><a name="user-content-2-kernel21kernelreadme210" href="#2-kernel21kernelreadme210" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2. kernel2.1修改详细描述(该部分取自于kernel/README中的2.1.0版本描述)</h2>
<h3 id="21-kernel"><a name="user-content-21-kernel" href="#21-kernel" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.1 增加kernel版本升级机制</h3>
<ul>
<li>增加etc/makefile.version文件<br />
   如果需要使用新版本底层库,直接在server中使用XIP_KLIBS.<br />
   对应版本即可具体版本信息参见makefile.version中说明</li>
<li>配合头文件xipversion.h使用</li>
</ul>
<h3 id="22-kcfglib"><a name="user-content-22-kcfglib" href="#22-kcfglib" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.2 修改了kcfglib</h3>
<ul>
<li>定义为2.1.0, 本次又修改了XIPCHKIP.cfg的检查方式， 如果未配置，则默认不校验，而不是报错.</li>
</ul>
<h3 id="23-kloglib"><a name="user-content-23-kloglib" href="#23-kloglib" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.3 修改了kloglib</h3>
<ul>
<li>定义为2.1.0版本，参考鞍山zlog作为版本使用,但是修改了服务程序部分，使用zlog不需要修改main函数。</li>
<li>修改logid的生成规则，考虑到集群的情况,根据机器标识等设置为不重复的将日志中的时间单独打印出来，<br />
   不在logid中体现,因为logid毕竟长度只有20</li>
<li>增加etc/xip_zlog.conf日志库规则配置文件，具体配置规则参见<a href="http://hardysimpson.github.io/zlog/UsersGuide-CN.html">zlog说明</a></li>
</ul>
<h3 id="24-kinitlib"><a name="user-content-24-kinitlib" href="#24-kinitlib" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.4 修改了kinitlib</h3>
<ul>
<li>定义为2.0.1版本,调用了在kloglib中封装的XipLogInit函数，以去掉同鞍山服务版本的，需要修改服务程序的限制.<br />
   zlog的加载在XipInit开始处执行,zlog的释放目前没有更好的解决办法，<br />
   因为 进程退出时没有kernel函数调用，不过进程已经退出了，资源则系统会释放.<br />
   目前暂时如此使用，后续有机会再调整服务程序，增加统一的kernel释放程序</li>
</ul>
<h3 id="25-kdblib"><a name="user-content-25-kdblib" href="#25-kdblib" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.5 修改了kdblib</h3>
<ul>
<li>定义为kdblib2.1.0版本，增加了从序列中获取流水号的相关功能.</li>
</ul>
<h3 id="26-kpublib"><a name="user-content-26-kpublib" href="#26-kpublib" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.6 修改了kpublib</h3>
<ul>
<li>定义为kpublib1.1.1版本(基于kpublib.1.1),修改了流水号获取方式依赖kdblib2.1.0的修改. <br />
   优化了一些函数的小BUG和编译警告.</li>
</ul>
<h3 id="27-etcxipsyscfg"><a name="user-content-27-etcxipsyscfg" href="#27-etcxipsyscfg" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.7 修改etc/XIPSYS.cfg</h3>
<ul>
<li>增加&rdquo;XIPMACHID&rdquo;配置字段,用于区分集群部署下的不同渠道机器.</li>
</ul>
<h3 id="28-vdmpvdmp"><a name="user-content-28-vdmpvdmp" href="#28-vdmpvdmp" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.8 (VDMP服务端)修改VDMP的服务端程序</h3>
<ul>
<li>优化了表操作函数和头文件的部分调用修改了生成头文件规则,增加了表操作函数的声明和#ifndef的重复包含判断.</li>
</ul>
<h3 id="29-inclkernel"><a name="user-content-29-inclkernel" href="#29-inclkernel" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.9 修改/新增incl/kernel/的头文件：</h3>
<p>头文件的修改如果有版本冲突，则使用宏定义控制,务必保证向下兼容性。</p>
<ul>
<li>
<p>syspub.h</p>
<ul>
<li>增加了zlog的引用</li>
<li>增加了全局变量xipMachId,xipTrdName</li>
</ul>
</li>
<li>
<p>xipcmstc.h</p>
<ul>
<li>增加ifndef的防止重复引用</li>
</ul>
</li>
<li>
<p>xipversion.h:</p>
<ul>
<li>新增kernel/下各个库的版本规划和定义</li>
<li>每次新增升级kernel下子库版本,kernel的xip版本也需要调整</li>
<li>总体说明参见etc/makefile.version</li>
<li>makefile.version的版本一定要与xipversion.h版本一致</li>
</ul>
</li>
<li>
<p>xiplocal.h</p>
<ul>
<li>新增客户差异化头文件，如果有差异定义，在此文件定义</li>
<li>通常情况，应该只有默认kernel版本的定义，尽量不要定义</li>
<li>特殊内容，以保持kernel标准化</li>
</ul>
</li>
<li>
<p>kfuncdecl.h</p>
<ul>
<li>增加各个提供出来给业务程序使用的函数的定义</li>
<li>对参数中的JA,xip等使用不透明指针</li>
<li>对于各系统内部使用的函数</li>
</ul>
</li>
<li>
<p>tabincl/下各xip头文件重新生成</p>
<ul>
<li>增加了ifndef的重复包含</li>
<li>增加了表操作函数的声明</li>
<li>配合VDMP服务端进行了修改</li>
</ul>
</li>
</ul>
<h3 id="210-tfquartzjar"><a name="user-content-210-tfquartzjar" href="#210-tfquartzjar" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>2.10 新增了tfquartz的相关jar包,配置文件</h3>
<ul>
<li>
<p>需要JDK1.6以上版本</p>
</li>
<li>
<p>新增了tfquartz数据库用户</p>
<ul>
<li>cron_config 定时人工配置表</li>
<li>cron_log 定时执行日志表(需要定时进行清理)</li>
</ul>
</li>
<li>
<p>新增bin/tfquartz.jar为tfquartz的服务执行程序</p>
</li>
<li>
<p>新增了tfquartz.sh管理脚本</p>
<ul>
<li>tfquartz.sh start 启动服务</li>
<li>tfquartz.sh stop 停止服务</li>
<li>tfquartz.sh load 加载服务(每次修改配置后执行,从cron_config表中加载到quartz系统表)</li>
<li>tfquartz.sh version 版本说明</li>
<li>tfquartz.sh clear 清空定时任务</li>
<li>tfquartz.sh install 首次安装(建表)</li>
</ul>
</li>
</ul>
<h2 id="3"><a name="user-content-3" href="#3" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>3. 开发环境升级步骤:</h2>
<p>本次更新分全量更新和增量更新两种模式，以后的kernel更新都是两种模式，主要分别在lib/下so的更新方式。</p>
<ul>
<li>全量更新:</li>
</ul>
<p>使用新版本的kernel库文件，完全替换原有库文件。<br />
以libklog2.1.0.so为例，将原libkloglib.so删除，然后ln -s 创建新的libkloglib.so指向libklog2.1.0.so<br />
相当于更新了所有的业务系统。有一定的风险性，需要一定各系统进行一定的测试,并且需要重启所有服务。一般用于新上业务系统或者大规模升级(如集群部署等)</p>
<ul>
<li>增量更新:</li>
</ul>
<p>使用新版本的kernel库文件，与原库文件并存。<br />
以libkloglib2.1.0.so为例，将原libkloglib.so不动，新业务系统指定链接库版本为-lkloglib2.1.0,则可以使用新的kernel</p>
<ul>
<li>以下更新为全量更新内容，增量不需要更新部分会有标记<strong>全量</strong>字样</li>
</ul>
<h3 id="31"><a name="user-content-31" href="#31" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>3.1 更新配置文件:</h3>
<ul>
<li>1) 更新<em>makefile.version</em>到etc/目录下</li>
<li>2) 在<em>etc/makefile.xip</em>中最后一行加入<code>"include $HOME/etc/makefile.version"</code>(参考makefile.xip.add)</li>
<li>3) 在<em>XIPSYS.cfg</em>中，参照etc/XIPSYS.cfg增加<code>"XIPMACHID"</code>配置(参考XIPSYS.cfg.add)</li>
<li>4) 更新<em>xip_zlog.conf</em>到etc/目录下</li>
<li>5) 更新<em>tfquartz.cfg</em>到etc/目录下,根据数据库中的用户，密码，SID信息对应修改</li>
</ul>
<h3 id="32-binbinsh"><a name="user-content-32-binbinsh" href="#32-binbinsh" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>3.2 更新可执行文件(bin和binsh)</h3>
<ul>
<li>1) 检查环境是否有JDK且JDK版本要&gt;=1.6,没有则需要另行安装(如果环境中有多个JDK，则可以修改tfquartz.sh脚本export JAVA_HOM等环境变量)</li>
<li>2) 更新tfquartz.jar 到 bin/下</li>
<li>3) 更新tfquartz.sh 到 binsh/下,赋予执行权限</li>
<li>4) 修改xipstart.sh 和xipstop.sh，去掉crontab的加载和删除内容,增加tfquartz启动(参考xipstart.sh.add)</li>
<li>5) 修改zjjk.sh 到 binsh/下, 赋予执行权限</li>
</ul>
<h3 id="33"><a name="user-content-33" href="#33" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>3.3 数据库新建和初始化</h3>
<ul>
<li>1) 新建tfquartz数据库用户,需要有创建表和索引的权限.</li>
<li>2) 配置tfquartz.cfg中的数据库相关信息</li>
<li>3) 执行<code>*tfquartz.sh install*</code>,初始化tfquartz库.</li>
<li>4) 根据定时需求配置cron_config表,cron_log表用于记录定时执行情况,<blockquote>
<p>具体tfquartz的详细安装，配置，参见《tfquartz使用手册》</p>
</blockquote>
</li>
<li>5) 参考生产整理流水号表<em>xip_chnlasstinfo</em>, 梳理流水号区间.如增量更新，建议新的业务系统不使用XipGetTraceno<ul>
<li>STEP1: 先将生产流水号同步到开发上,开始梳理.注意开发比生产多的，不要全表覆盖了</li>
<li>STEP2: 需要保证同一个shm_key的所有渠道的sem_key, minseq, maxseq必须一致.<ul>
<li>sem_key一般和shm_key一致，不一致进行修改.</li>
<li>min_seq, max_seq要一致，如果不一直，如果确定某个配置有问题，按统一配置修改。如果不确定<br />
按最小区间修改，但是最小区间不能小于预估业务量</li>
</ul>
</li>
<li>STEP3: 保留shm_key为0的渠道，如果有调整为其他渠道. 统一将不使用流水号的渠道，或废弃的渠道，shm_key统一规划为0,最小值为0,最大值为99999999</li>
</ul>
</li>
</ul>
<h3 id="33_1"><a name="user-content-33_1" href="#33_1" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>3.3 头文件更新</h3>
<ul>
<li>1) mv原src/incl/kernel文件夹到备份目录下</li>
<li>2) 将更新包中的incl/kernel文件夹 更新到src/incl/kernel目录下</li>
<li>3) 对比原incl/kernel和新更新kernel有无变化，一切应该以新kernel为准。<br />
     如本地有特殊修改，需要先联系kernel版本管理人员。经过讨论后，再在xiplocal.h补充定义。</li>
<li>4) 将incl/zlog文件夹，更新到src/incl下</li>
</ul>
<h3 id="34-kernel"><a name="user-content-34-kernel" href="#34-kernel" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>3.4 kernel程序更新</h3>
<ul>
<li>1) mv原来src/kernel或者.kernel版本，备份,除鞍山和锦州外，其他地方不要保留kernel源代码</li>
<li>2) 备份原来的lib/libk*开头的so文件</li>
<li>3) 将更新包中的lib库中的so/a文件更新到现场lib/下</li>
<li>4) <strong>全量更新</strong> 强制使用2.1版本为默认版本。将本次更新的so文件，替换为原so文件.<br />
以libkloglib2.1.0.so为例，全量更新则删除原<em>libkloglib.so</em>文件，执行<code>*ln -s libkloglib2.1.0.so libkloglib.so*</code><br />
更新包中的lib文件夹下，提供了2.1.0版本更新的脚本,但是需要确认后才能执行.需要确认的事项为，如当前环境原来已经有版本<br />
文件，如libkpublib.1.1.so，则该文件也要删除掉并使用<em>ln -s</em>进行链接。</li>
</ul>
<blockquote>
<p>需要在新业务系统中指定kernel版本,具体参见《渠道kernel使用和升级规范》</p>
</blockquote>
<h3 id="35"><a name="user-content-35" href="#35" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>3.5 启动服务</h3>
<ul>
<li>1) 重启当前渠道运行服务</li>
<li>2) 查看日志是否正常写入</li>
<li>3) 执行crontab -r 去掉当前所有定时</li>
<li>4) 启动tfquartz:<br />
    &ndash;tfquartz.sh start<br />
    &ndash;tfquartz.sh load</li>
</ul>
<h3 id="36-005b005c"><a name="user-content-36-005b005c" href="#36-005b005c" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>3.6 补充更新（总线005B和005C的更新）</h3>
<p>请检查<em>005B</em>和<em>005C</em>数据总线是否存在，如果不存在，补充更新<br />
此更新为二代支付上线时就应该更新的内容，但是个别地方并未更新，在此一并更新<br />
- 1) 使用开发环境VDMP，定义总线功能，增加005B和005C的定义<br />
- 2）需要注意的时候，xip_seq是顺序排列的,因此不要直接sql导入两条，发需要使用VDMP，使用定义总线更新.<br />
生产上需要核对后导入xip_databus表信息。<br />
请参照下表信息配置更新:</p>
<table>
<thead>
<tr>
<th>seq</th>
<th>code</th>
<th>dataalias</th>
<th>level</th>
<th>ioflag</th>
<th>datatype</th>
<th>len</th>
<th>dec</th>
<th>desc</th>
</tr>
</thead>
<tbody>
<tr>
<td>44</td>
<td>005B</td>
<td>CommErrorCode</td>
<td>0</td>
<td>N</td>
<td>0</td>
<td>10</td>
<td>0</td>
<td>系统通讯级响应码</td>
</tr>
<tr>
<td>45</td>
<td>005C</td>
<td>MaxCycCnt</td>
<td>1</td>
<td>N</td>
<td>2</td>
<td>8</td>
<td>0</td>
<td>DOWHILE脚本最大循环次数</td>
</tr>
</tbody>
</table>
<h2 id="4"><a name="user-content-4" href="#4" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>4. 生产环境升级步骤:</h2>
<p><strong>!!!生产环境的更新，需要根据开发环境的测试结果，进行再次打包更新，本更新包中的所有更新<br />
信息，都是开发环境使用的，生产需要参照开发更新包，进行配置信息等的本地化处理后，自行打包</strong></p>
<h3 id="41"><a name="user-content-41" href="#41" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>4.1 检查和调整(重要)</h3>
<ul>
<li>1) 检查xip_chnlasstinfo表中，是否有相同shm_key值，但是最小值和最大值配置不相同的.<br />
       该种配置属于配置错误，需要调整正确.具体参见开发更新检查步骤</li>
<li>2) 根据生产etc/cron下的定时文件，配置到cron_config中(再开发配置完成)<br />
       &ndash;需要注意如果cron中有使用$HOME这种变量，则需要写全路径，或者不写路径.<br />
         tfquartz调用定时会使用其启动服务时候的环境变量</li>
<li>3) 查看xip_databus数据总线，并和开发环境进行比对，比较是否生产和开发环境有差异.<br />
       如果只有新增的数据编码，则才可以直接开发全量更新。</li>
</ul>
<h3 id="42"><a name="user-content-42" href="#42" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>4.2 备份</h3>
<ul>
<li>1) 备份etc/ lib/文件夹</li>
<li>2) 备份数据库xip.xip_chnlasstinfo表数据</li>
<li>3) 备份数据库xip.xip_databus表数据</li>
<li>4) 备份其他本次业务要更新的数据</li>
</ul>
<h3 id="43"><a name="user-content-43" href="#43" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>4.3 更新时间选择</h3>
<p>如果是<strong>全量更新</strong>模式，则需要选择在渠道日切前更新，日切后启用新流水，防止流水号重复:<br />
- 日切前傍晚: 定义为before<br />
    - 1) 将etc/ binsh/ tfquartz.jar等更新到生产上, db<br />
    - 2）更新带有版本信息的so库,但是不要执行ln_lib.sh<br />
- 日切之后更新的文件夹，定义为after<br />
    - 3) 待渠道收到日切通知之后,停止渠道所有服务<br />
    - 4) 更新lib,更新db（chnlasstinfo，databus）</p>
<ul>
<li>
<p>核心通知渠道日切之后，可能会上来业务，如果恰巧该业务流水号重置,则<br />
流水仍旧从原共享内存取值了个别交易，可能会导致流水号重复的问题,此种情况有极小可能发生，后续问题查找需要注意。</p>
</li>
<li>
<p>需要特殊注意，如果日切时间为11点左右，停止服务之后，一定要注意银联日期是否改变，如果已经日切，则不要忘记修改银联日期.</p>
</li>
</ul>
<p>问题查找的时候需要注意。</p>
<p>如果是增量跟新模式，则无影响，随时可以更新,因为业务库已经指定了版本信息</p>
<h3 id="44"><a name="user-content-44" href="#44" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>4.4 更新包更新</h3>
<p>需要注意相关配置文件开发和生产上的差异性，比如数据库密码, 配置文件路径等等<br />
- before文件夹可以在日切提前更新：<br />
    - 1) lib库更新<br />
        执行2.sh ，检查是否更新完全<br />
    - 2) bin更新<br />
        更新tfquartz.jar到开发环境<br />
    - 3) binsh更新<br />
        更新下面所有.sh文件,赋值可执行权限<br />
    - 4) etc更新<br />
        更新下面所有的配置文件到生产etc下<br />
    - 5) db/<br />
       &ndash;执行tfquartz.sh install<br />
       &ndash;将CRON_CONFIG_TABLE.sql导入到tfquartz用户中</p>
<ul>
<li>after文件夹在日切后更新<ul>
<li>1) 收到核心日切通知,xipstop.sh停止所有服务,并检查是否都停止完成</li>
<li>2) 更新db/下 xip_databus.sql表数据和xip_chnlasstinfo表数据</li>
<li>3) 更新lib/下的库文件<br />
   执行ln_lib.sh脚本，将默认kernel版本软连接为2.1版本</li>
<li>4) 更新bin/下可执行程序,并赋值可执行权限</li>
</ul>
</li>
</ul>
<h3 id="45"><a name="user-content-45" href="#45" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>4.5 启动服务</h3>
<ul>
<li>1) 检查更新是否完全</li>
<li>2) 如果是全业务更新,则停止所有渠道服务xipstop.sh，使用ps -ef|grep xip查看是否还有剩余进程并停止</li>
<li>3) 如果是全业务更新,启动所有渠道服务</li>
<li>4) 查看日志输出等是否正常</li>
</ul>
<h3 id="46"><a name="user-content-46" href="#46" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>4.6 业务验证</h3>
<ul>
<li>1) ATM业务，查看是否有MONLOG，普通APPLOG，流水号是否正常</li>
<li>2) 网银/手机银行常用业务</li>
<li>3) 柜面24小时常用业务</li>
</ul>
<h2 id="5"><a name="user-content-5" href="#5" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>5. 辅助检查和更新,以及特殊注意事项</h2>
<h3 id="51-kernel"><a name="user-content-51-kernel" href="#51-kernel" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>5.1 检查是否当地擅自修改了kernel</h3>
<p>如果已经擅自修改了kernel.需要将kernel修改部分单独提取出来<br />
形成单独的so库，再进行更新. 以铁岭为例，铁岭现在在kloglib中增加了Mlog和CTSLOG,用于<br />
统计柜面业务和银联/IC卡业务来帐监控，则需要将原Mlog和CTSLOG提出，新建一个liblogtlbank.so<br />
并更新使用到的库的makefile :counter/pkglib,  cuic/service  cups/service</p>
<h3 id="52-005b005c"><a name="user-content-52-005b005c" href="#52-005b005c" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>5.2 总线更新005B和005C 补充更新</h3>
<p>总线更新已经提到，对环境没有影响，随时可以更新</p>
<h3 id="53"><a name="user-content-53" href="#53" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>5.3 检查流水号重复区间<strong>非常非常重要</strong></h3>
<p>无论是全业务更新还是单独更新，都需要调整流水号。<br />
流水号的问题必须在本次更新中解决，否则可能会影响序列的使用。<br />
其实流水号如果配置有问题，在原kernel也有问题，只不过大家没注意罢了。</p>
<h3 id="54-vdmp"><a name="user-content-54-vdmp" href="#54-vdmp" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>5.4 VDMP的更新，除鞍山版本，其他地方都可以全量替换</h3>
<h3 id="55-xiplogid"><a name="user-content-55-xiplogid" href="#55-xiplogid" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>5.5 xipLogId的使用长度调整，需要辅助调整其他更新</h3>
<p>由于原xipLogId定义为21位长，但是只使用了17位长，因此很多业务程序在使用xipLogId的时候，直接写死17位<br />
如果有该种问题，则必须要调整程序，目前发现的系统有:<br />
        cnaps2 , cmserv, esbxml的拆组包和自动发送<br />
        cnaps2/pcron/server, cnaps2/pcron/commlib<br />
        cmserv/commlib<br />
        esbxml/commlib</p>
<h3 id="56-xiplogcreachanlogid"><a name="user-content-56-xiplogcreachanlogid" href="#56-xiplogcreachanlogid" class="headeranchor-link" aria-hidden="true"><span class="headeranchor"></span></a>5.6 由于增加了XipLogCrea/Chan函数,增加logid关联，相关拆组包可以调整,以下为铁岭修改的业务程序</h3>
<p>esbxml的渠道配置，如EHOST-F要配合更新(XIPIN)<br />
cnaps2 , cmserv, esbxml的拆组包和自动发送<br />
cnaps2/pcron/server, cnaps2/pcron/commlib<br />
cmserv/commlib<br />
esbxml/commlib</p></article></body></html>